| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205 |
1
1
6
6
6
6
6
6
6
6
6
6
6
1
5
5
5
4
4
4
4
4
1
1
3
2
1
1
2
1
1
5
5
5
5
5
5
1
1
4
3
1
1
1
1
| var _ = require('../utility');
var logger = require('./logger');
/*
* accessToken may be embedded in payload but that should not
* be assumed
*
* options: {
* hostname
* protocol
* path
* port
* method
* }
*
* params is an object containing key/value pairs. These
* will be appended to the path as 'key=value&key=value'
*
* payload is an unserialized object
*/
function get(accessToken, options, params, callback, requestFactory) {
if (!callback || !_.isFunction(callback)) {
callback = function() {};
}
_.addParamsAndAccessTokenToPath(accessToken, options, params);
var method = 'GET';
var url = _.formatUrl(options);
_makeRequest(accessToken, url, method, null, callback, requestFactory);
}
function post(accessToken, options, payload, callback, requestFactory) {
if (!callback || !_.isFunction(callback)) {
callback = function() {};
I}
if (!payload) {
return callback(new Error('Cannot send empty request'));
I}
var stringifyResult = _.stringify(payload);
if (stringifyResult.error) {
return callback(stringifyResult.error);
I}
var writeData = stringifyResult.value;
var method = 'POST';
var url = _.formatUrl(options);
_makeRequest(accessToken, url, method, writeData, callback, requestFactory);
}
function _makeRequest(accessToken, url, method, data, callback, requestFactory) {
var request;
if (requestFactory) {
request = requestFactory();
E} else {
request = _createXMLHTTPObject();
}
if (!request) {
// Give up, no way to send requests
return callback(new Error('No way to send a request'));
}
try {
try {
var onreadystatechange = function() {
try {
if (onreadystatechange && request.readyState === 4) {
onreadystatechange = undefined;
E
var parseResponse = _.jsonParse(request.responseText);
if (_isSuccess(request)) {
callback(parseResponse.error, parseResponse.value);
return;
} else if (_isNormalFailure(request)) {
if (request.status === 403) {
// likely caused by using a server access token
var message = parseResponse.value && parseResponse.value.message;
logger.error(message);
}
// return valid http status codes
callback(new Error(String(request.status)));
} else {
// IE will return a status 12000+ on some sort of connection failure,
// so we return a blank error
// http://msdn.microsoft.com/en-us/library/aa383770%28VS.85%29.aspx
var msg = 'XHR response had no status code (likely connection failure)';
callback(_newRetriableError(msg));
}
}
} catch (ex) {
//jquery source mentions firefox may error out while accessing the
//request members if there is a network error
//https://github.com/jquery/jquery/blob/a938d7b1282fc0e5c52502c225ae8f0cef219f0a/src/ajax/xhr.js#L111
var exc;
if (ex && ex.stack) {
exc = ex;
} else {
exc = new Error(ex);
}
callback(exc);
}
};
request.open(method, url, true);
if (request.setRequestHeader) {
request.setRequestHeader('Content-Type', 'application/json');
E request.setRequestHeader('X-Rollbar-Access-Token', accessToken);
}
request.onreadystatechange = onreadystatechange;
request.send(data);
} catch (e1) {
// Sending using the normal xmlhttprequest object didn't work, try XDomainRequest
if (typeof XDomainRequest !== 'undefined') {
I // Assume we are in a really old browser which has a bunch of limitations:
// http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
// Extreme paranoia: if we have XDomainRequest then we have a window, but just in case
if (!window || !window.location) {
return callback(new Error('No window available during request, unknown environment'));
}
// If the current page is http, try and send over http
if (window.location.href.substring(0, 5) === 'http:' && url.substring(0, 5) === 'https') {
url = 'http' + url.substring(5);
}
var xdomainrequest = new XDomainRequest();
xdomainrequest.onprogress = function() {};
xdomainrequest.ontimeout = function() {
var msg = 'Request timed out';
var code = 'ETIMEDOUT';
callback(_newRetriableError(msg, code));
};
xdomainrequest.onerror = function() {
callback(new Error('Error during request'));
};
xdomainrequest.onload = function() {
var parseResponse = _.jsonParse(xdomainrequest.responseText);
callback(parseResponse.error, parseResponse.value);
};
xdomainrequest.open(method, url, true);
xdomainrequest.send(data);
} else {
callback(new Error('Cannot find a method to transport a request'));
}
}
} catch (e2) {
callback(e2);
}
}
function _createXMLHTTPObject() {
/* global ActiveXObject:false */
var factories = [
function () {
return new XMLHttpRequest();
},
function () {
return new ActiveXObject('Msxml2.XMLHTTP');
},
function () {
return new ActiveXObject('Msxml3.XMLHTTP');
},
function () {
return new ActiveXObject('Microsoft.XMLHTTP');
}
];
var xmlhttp;
var i;
var numFactories = factories.length;
for (i = 0; i < numFactories; i++) {
/* eslint-disable no-empty */
try {
xmlhttp = factories[i]();
break;
} catch (e) {
// pass
}
/* eslint-enable no-empty */
}
return xmlhttp;
}
function _isSuccess(r) {
return r && r.status && r.status === 200;
}
function _isNormalFailure(r) {
return r && _.isType(r.status, 'number') && r.status >= 400 && r.status < 600;
}
function _newRetriableError(message, code) {
var err = new Error(message);
err.code = code || 'ENOTFOUND';
return err;
}
module.exports = {
get: get,
post: post
};
|